use bits::{BitsOps, IntoBits};

use crate::{Elf64Addr, Elf64Half, Elf64Word, Elf64Xword};

#[repr(C)]
pub struct Sym {
    pub name: Elf64Word,
    pub info: SymInfo,
    pub other: u8,
    pub shndx: Elf64Half,
    pub value: Elf64Addr,
    pub size: Elf64Xword,
}

impl_borrow!(Sym);

trans! {
    SymBind:u8,
    SymType:u8,
    SymInfo:u8
}
impl SymInfo {
    pub fn new(sym_bind: SymBind, sym_type: SymType) -> Self {
        SymInfo {
            data: 0u8
                .bits(0..=3)
                .write(sym_type.data)
                .bits(4..=7)
                .write(sym_bind.data),
        }
    }
    pub fn sym_bind(&self) -> SymBind {
        SymBind {
            data: self.data.bits(4..=7).read(),
        }
    }
    pub fn sym_type(&self) -> SymType {
        SymType {
            data: self.data.bits(0..=3).read(),
        }
    }
}

def_const! {
    SymBind {
        LOCAL:  0,
        GLOBAL: 1,
        WEAK:   2
    }
    SymType {
        NOTYPE:     0,
        OBJECT:     1,
        FUNC:       2,
        SECTION:    3,
        FILE:       4,
    }
}
